
#pragma once

#include <cstdint>
#include <iostream>
#include <memory>
#include <string>
#include <cstring>
#include <cstdlib>  
#include <vector>
#include "amf.h"

enum ParserRtmpMsgStatus
{
    EmRtmpMsgUnknow,
    EmRtmpMsgNotEngouh,
    EmRtmpMsgSuccess,
    EmRtmpMsgError
};

class RtmpMessageBody;
class RtmpMessageHeader
{
public:
    RtmpMessageHeader();
    ParserRtmpMsgStatus ParseRtmpMsg(const uint8_t * data, int data_length, int & use_length);
    bool ParseRtmpMsgHeader(const uint8_t * data, int data_length, int & use_length);
    void ComposeHeader(uint8_t * data, int length, int & use_length);
    void ComposeDataToBuffer(uint8_t * data, int length, int & use_length);
public:
    uint8_t m_format;
    uint32_t m_chunk_stream_id;
    uint32_t m_time;        // take 3 byte
    uint32_t m_body_size;   // take 3 byte
    uint8_t  m_type_id;
    uint32_t m_stream_id;
    uint32_t m_duration;
    std::shared_ptr<RtmpMessageBody> m_rtmp_body;
};

class RtmpMessageBody
{
public:
    RtmpMessageBody();
    ~RtmpMessageBody();
    ParserRtmpMsgStatus ParseRtmpMsgBody(const uint8_t * data, int data_length, int body_size, int & use_length);
    std::vector<AmfValue*> & GetContent() {   return m_content_vec;   }
    void ComposeBodyData(uint8_t * data, int length, int & use_length);
    int BodySize();
    double GetNumberValue();
    std::string GetFirstStr();
    void AddAmfValue(AmfValue * value);
private:
public:
    std::vector<AmfValue*> m_content_vec;
};

class RtmpPacketMsg
{
public:
    RtmpPacketMsg();
    int PushData(const uint8_t * data, int length);
    bool IsComplete();
    void AddRtmpMsg(RtmpMessageHeader & msg);
public:
    RtmpMessageHeader     m_header;
    std::vector<RtmpPacketMsg> m_rtmp_msg_vec;
    std::vector<uint8_t> m_body_data;
};


